#include "io.h"
#include "hal.h"

#define TICKS_PER_US                (32UL)
#define TOTAL_TICKS                 (32000000UL / (1000 / HZ_RTOS_SYS_TICK_PERIOD))  

err_t tick_configuration(void)
{
  SysTick_Config(SystemCoreClock / (1000 / HZ_RTOS_SYS_TICK_PERIOD));
  
  return 0;
}
HAL_FUNC_EXPORT(tick_configuration, init the systick and its count function, 1);

extern void SysTick_Handler(void)
{
    extern void os_timetick(void);
    
    os_timetick();
}

INLINE int get_end_ticks(int start_ticks, int us)
{
    int total_ticks = TICKS_PER_US * us;
    
    if (total_ticks > start_ticks)
        return start_ticks + TOTAL_TICKS - total_ticks;
    else
        return start_ticks - total_ticks;
}

INLINE int get_current_ticks(void)
{
    return SysTick->VAL;
}

INLINE void __delay_us(int us)
{
    int start_ticks = get_current_ticks();
    int end_ticks = get_end_ticks(start_ticks, us);
    int flag = (end_ticks < start_ticks) ? 1 : 0;
    
    while (1)
    {
        int current_ticks = get_current_ticks();
        
        if (flag)
        {
            if (current_ticks >= start_ticks || current_ticks <= end_ticks)
                break;
        }
        else
        {
            if (current_ticks >= start_ticks && current_ticks <= end_ticks)
                break;
        }
    }
}

extern void udelay(unsigned int us)
{
    phys_reg_t temp;
    
    temp = hz_hw_interrupt_suspend();
    
    __delay_us(us);
    
    hz_hw_interrupt_recover(temp);
}

extern void mdelay(unsigned int ms)
{
    phys_reg_t temp;
    
    temp = hz_hw_interrupt_suspend();
    
    while (ms--)
        __delay_us(1000);
    
    hz_hw_interrupt_recover(temp);
}
